feat(security-contacts): implement tier D#4373
Conversation
Signed-off-by: Mouad BANI <mouad-mb@outlook.com>
Signed-off-by: Mouad BANI <mouad-mb@outlook.com>
PR SummaryMedium Risk Overview GitHub fallbacks run in parallel only in that case: top committers from the last 90 days (bots filtered, contributor stats polled on HTTP 202) plus repo owner handle and optional public profile email. Go packages get static registry contacts ( Pipeline wiring: Reviewed by Cursor Bugbot for commit 729f6a5. Bugbot is set up for automated code reviews on this repo. Configure here. |
|
|
|
Your PR title doesn't contain a Jira issue key. Consider adding it for better traceability. Example:
Projects:
Please add a Jira issue key to your PR title. |
There was a problem hiding this comment.
Pull request overview
Adds Tier D fallback security-contact extraction for GitHub repositories and Go packages.
Changes:
- Adds top-committer and repository-owner fallbacks.
- Activates fallbacks when higher-tier contacts are unavailable.
- Registers Go ecosystem contacts.
Metadata: PR title lacks the required (CM-XXX) suffix.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
processBatch.ts |
Integrates Tier D fallbacks. |
topCommitters.ts |
Extracts recent committers. |
repoOwner.ts |
Extracts repository-owner contacts. |
registry/index.ts |
Registers Go extraction. |
registry/go.ts |
Defines Go security contacts. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Signed-off-by: Mouad BANI <mouad-mb@outlook.com>
| const path = `/repos/${owner}/${name}/stats/contributors` | ||
| let stats: ContributorStat[] | ||
| try { | ||
| const { text } = await deps.githubGet(path) |
Signed-off-by: Mouad BANI <mouad-mb@outlook.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit f6a517d. Configure here.
| if (isJunkContact(c)) return false | ||
| return c.channel !== 'email' || classifyEmailReachability(c.value).reachable | ||
| } | ||
| const hasUsableHigherTierContact = contacts.some((c) => c.tier !== 'D' && isUsableRaw(c)) |
There was a problem hiding this comment.
PVR guess blocks tier D
Medium Severity
The tier D gate treats tier B github-pvr contacts from SECURITY.md keyword inference as usable higher-tier contacts whenever isUsableRaw passes, even when pvrEnabled was never set to true. That skips fetchTopCommitters and fetchRepoOwner while only a speculative PVR URL remains—after the existing veto that drops github-pvr when PVR is explicitly disabled.
Reviewed by Cursor Bugbot for commit f6a517d. Configure here.
| const count = (stat.weeks ?? []).reduce((sum, week) => { | ||
| const w = typeof week.w === 'number' ? week.w : 0 | ||
| const c = typeof week.c === 'number' ? week.c : 0 | ||
| return w >= sinceUnixSeconds ? sum + c : sum |
| function isBotLogin(login: string): boolean { | ||
| const lower = login.toLowerCase() | ||
| if (lower.endsWith('[bot]')) return true | ||
| return BOT_TOKENS.some((token) => lower.includes(token)) | ||
| } |
Signed-off-by: Mouad BANI <mouad-mb@outlook.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (2)
services/apps/packages_worker/src/security-contacts/processBatch.ts:181
- The fallback gate still runs before CDP handle resolution and final reconciliation. A higher-tier GitHub handle can count as usable here, then
resolveCdpEmailscan link it to a disposable or non-GitHub noreply address;identityLinkMergeremoves the handle in favor of that email, which is finally marked unreachable. Tier D is then skipped even though the reconciled result has no reachable higher-tier contact. Resolve/reconcile the higher-tier candidates before evaluating this gate, and resolve any newly added Tier D handles afterward.
const hasUsableHigherTierContact = contacts.some((c) => c.tier !== 'D' && isUsableRaw(c))
services/apps/packages_worker/src/security-contacts/extractors/topCommitters.ts:46
- Substring matching classifies legitimate humans as bots: usernames such as
claude,claudette, or any login containingopenaiare discarded, and the same helper also rejects public emails containing those strings. GitHub already suppliesauthor.type; keep any fallback detection to precise bot-login patterns rather than generic brand-name substrings.
function matchesBotToken(value: string): boolean {
const lower = value.toLowerCase()
return BOT_TOKENS.some((token) => lower.includes(token))
| const path = `/repos/${owner}/${name}/stats/contributors` | ||
| const stats = await fetchContributorStats(path, target, owner, name, deps.githubGet, sleep) |


This pull request adds new fallback mechanisms for extracting security contacts from GitHub repositories, specifically targeting cases where no higher-tier, reachable contacts are found. It introduces two new extractors: one for identifying top committers and another for finding the repository owner, both of which supplement the existing contact extraction pipeline. Additionally, the pull request adds support for extracting Go ecosystem registry contacts.
New fallback contact extraction:
fetchTopCommittersextractor to identify the top human committers (by email and GitHub handle) from the past 90 days of repository history, excluding bots, and return them as security contacts.fetchRepoOwnerextractor to extract the repository owner's GitHub handle and, if available, their public email as security contacts.processRepoinprocessBatch.tsto invoke these new extractors only when no higher-tier, reachable contacts are found, ensuring more robust fallback contact coverage.Go ecosystem support:
fetchGoextractor for the Go package registry, returning the Go security team's contact email and web form as default contacts.